Python 多进程与多线程
如果你把上篇多线程和多进程的文章搞定了,那么要恭喜你了 。你编写爬虫的能力上了一个崭新的台阶。不过,我们还不能沾沾自喜,因为任重而道远。那么接下来就关注下本文的主要内容。本文主要介绍 urllib 库的代替品 —— Requests
。
1 Requests 简介
引用 Requests 官网的说明:
Requests is the only Non-GMO HTTP library for Python, safe for human consumption.
Requests 官方的介绍语是多么霸气。之所以能够这么霸气,是因为 Requests 相比 urllib 在使用方面上会让开发者感到更加人性化、更加简洁、更加舒服。并且国外一些知名的公司也在使用该库,例如 Google、Microsoft、Amazon、Twitter 等。因此,我们就更加有必要来学习 Request 库了。在学习之前,我们来看下它究竟具有哪些特性?
具体如下:
Keep-Alive & 连接池
国际化域名和 URL
带持久 Cookie 的会话
浏览器式的 SSL 认证
自动内容解码
基本/摘要式的身份认证
优雅的 key/value Cookie
自动解压
Unicode 响应体
HTTP(S) 代理支持
文件分块上传
流下载
连接超时
分块请求
支持 .netrc
2 安装 Requests
古人云:“工欲善其事,必先利其器”。在学习 Requests 之前,我们应先将库安装好。安装它有两种办法。
方法1:通过 pip 安装
比较推荐使用这种方式,既简单又方便管理。
方法2:通过源码安装
先通过 git 克隆源码库:
或者直接到 github 网页上下载源码压缩包
接着进入到 requests 目录中执行以下命令:
3 发起请求
有了前面学习 urllib 库的经验,现在我们学习 Requests 应该会更加容易上手。
3.1 简单抓取网页
我们使用 Requests 向百度贴吧发起一个 HTTP 请求,并获取到它页面的源代码。
那么使用 POST 请求网页,代码又该怎么写呢?相信答案已经浮现在你脑海中了。没错,就是将 get 换成 post 即可。
3.2 传递 URL 参数
我们在请求网页时,经常需要携带一些参数。Requests 提供了params
关键字参数来满足我们的需求。params 是一个字符串字典,我们只要将字典构建并赋给 params 即可。我们也无须关心参数的编码问题,因为 Requests 很人性化,会将我们需要传递的参数正确编码。它的具体用法如下:
如果字典为空是不会被拼接到 URL中的。另外,params 的拼接顺序是随机的,而不是写在前面就优先拼接。
你也许会疑问,为什么会有多了个”+”号呢?这个是 Requests 为了替代空格,它在请求时会自动转化为空格的。
3.3 构造请求头
为了将 Requests 发起的 HTTP 请求伪装成浏览器,我们通常是使用headers
关键字参数。headers 参数同样也是一个字典类型。具体用法见以下代码:
3.4 使用 data 参数提交数据
data 参数通常结合 POST 请求方式一起使用。如果我们需要用 POST 方式提交表单数据或者JSON数据,我们只需要传递一个字典给 data 参数。
提交表单数据
我们使用测试网页http://httpbin.org/post
来提交表单数据作为例子进行展示。
运行结果如下:我们会看到http://httpbin.org/post
页面打印我们的请求内容中,有form
字段。
提交 JSON 数据
在HTTP 请求中,JSON 数据是被当作字符串文本。所以,我们使用 data 参数的传递 JSON 数据时,需要将其转为为字符串。我们继续使用上文的代码做演示。
你可以拿下面的运行结果和提交表单数据的运行结果做下对比,你会了解更加清楚两者的差异。
那是否有更加简便的方法来传递 JSON 数据?Requests 在 2.4.2 版本新增该功能。我们可以使用 json 参数直接传递,然后它会被自动编码。
3.5 使用代理
有些网站做了浏览频率限制。如果我们请求该网站频率过高,该网站会被封掉我们的 IP,禁止我们的访问。所以我们需要使用代理来突破这“枷锁”。这里需要用到proxies
参数,proxies 也是一个字典类型。具体用法如下:
除了支持 HTTP 代理,Requests 在 2.10 版本新增支持 SOCKS 协议的代理。也就是说,Requests 能够使用 ShadowSocks 代理。看到这里,你的内心是不是有点小激动?
使用 SOCKS 代理,需要额外安装一个第三方库,我们就使用 pip 来安装。
安装成功之后,就可以正常使用了,用法跟 HTTP 代理相关。具体见代码:
3.6 设置请求超时
我们使用代理发起请求,经常会碰到因代理失效导致请求失败的情况。因此,我们对请求超时做下设置。当发现请求超时,更换代理再重连。
如果你要同时设置 connect 和 read 的超时时间,可以传入一个元组进行设置。
3.7 使用 Cookie
想在响应结果中获取 cookie 的一些值,可以直接访问。
想发送 cookies 到服务器,可以使用cookies
参数。同样该参数也是字典类型
4 响应结果
我们跟Python 打交道,摆脱不了编码的问题。使用 Requests 请求,我们无需担心编码问题。感觉 Requests 真的是太人性化了。请求发出后,Requests 会基于 HTTP 头部对响应的编码作出有根据的推测。当你访问 response .text 之时,Requests 会使用其推测的文本编码。
如果你想改变 response 的编码格式,可以这么做:
4.1 二进制响应内容
对于非文本请求, 我们能以字节的方式访问请求响应体。Requests 会自动为我们解码 gzip 和 deflate 传输编码的响应数据。
例如,以请求返回的二进制数据创建一张图片,你可以使用如下代码:
4.2 JSON 响应内容
Requests 中也有一个内置的 JSON 解码器,助我们处理 JSON 数据:
如果 JSON 解码失败, response .json() 就会抛出一个异常。例如,响应内容是 401 (Unauthorized),尝试访问 response .json() 将会抛出 ValueError: No JSON object could be decoded 异常。
4.3 响应状态码
我们需要根据响应码来判断请求的结果,具体是这样获取状态码:
Requests 内部提供了一个状态表,如果有需要对状态码进行判断,可以看下requests.codes
的源码。
5 高级用法
5.1 重定向与请求历史
有些页面会做一些重定向的处理。Requests 又发挥人性化的特性。它在默认情况下,会帮我们自动处理所有重定向,包括 301 和 302 两种状态码。我们可以使用response .history
来追踪重定向。
Response.history
是一个 Response 对象的列表,为了完成请求而创建了这些对象。这个对象列表按照从最老到最近的请求进行排序。
如果我们要禁用重定向处理,可以使用allow_redirects
参数:
5.2 会话
Requests 支持 session 来跟踪用户的连接。例如我们要来跨请求保持一些 cookie,我们可以这么做:
5.3 身份认证
有些 web 站点都需要身份认证成功之后才能访问。urllib 具备这样的功能,Requests 也不例外。Requests 支持基本身份认证(HTTP Basic Auth)、netrc 认证、摘要式身份认证、OAuth 1 认证等。
基本身份认证
许多要求身份认证的web服务都接受 HTTP Basic Auth。这是最简单的一种身份认证,并且 Requests 对这种认证方式的支持是直接开箱即可用。HTTP Basic Auth 用法如下:
摘要式身份认证
摘要式是 HTTP 1.1 必需的第二种身份验证机制。这种身份验证由用户名和密码组成。随后将用 MD5(一种单向哈希算法)对摘要式身份验证进行哈希运算,并将其发送到服务器。具体用法如下:
OAuth 认证
OAuth(开放授权)认证在我们的生活中随处可见。Requests 同样也支持这中认证方式,其中包括 OAuth 1.0 和 OAuth 2.0。如果你需要用到该认证,你需要安装一个支持库requests-oauthlib
。我以 OAuth 1.0 认证作为例子进行讲解:
作者:猴哥,公众号:极客猴。爱好读书,喜欢钻研技术,梦想成为文艺青年的IT Boy。
- END -
分享干货的公众号